package com.thirtydays.frame.base

import android.graphics.Color
import android.graphics.drawable.AnimationDrawable
import android.os.Bundle
import android.view.*
import android.widget.RelativeLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.RecyclerView
import androidx.viewbinding.ViewBinding
import com.azhon.appupdate.manager.DownloadManager
import com.blankj.utilcode.util.ToastUtils
import com.thirtydays.frame.R
import com.thirtydays.frame.base.bean.EventMessage
import com.thirtydays.frame.data.DataManager
import com.thirtydays.frame.databinding.FragmentBaseBinding
import com.thirtydays.frame.databinding.FragmentBaseRvBinding
import com.thirtydays.frame.databinding.LayoutLoadingEmptyBinding
import com.thirtydays.frame.databinding.LayoutLoadingErrorBinding
import com.thirtydays.frame.module.login.view.LoginActivity
import com.thirtydays.frame.util.ext.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.lang.reflect.ParameterizedType

/**
 * @创建者：小垚
 * @时间：2021/7/2212:27
 * @描述：
 */
abstract class BaseFragment<VM : BaseViewModel, SV : ViewBinding> : Fragment() {

    open val mAppViewModel: AppViewModel by lazy { getAppViewModel() }
    lateinit var mViewModel: VM
    lateinit var mViewBinding: SV
    lateinit var mBaseViewBinding: FragmentBaseBinding
    lateinit var mLoadingErrorBinding: LayoutLoadingErrorBinding

    // 是否是第一次加载
    var mIsVisible = true

    var mLoadingView: View? = null
    var mErrorView: View? = null
    var mAnimationDrawable: AnimationDrawable? = null

    val dispatcher by lazy { requireActivity().onBackPressedDispatcher }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val type = javaClass.genericSuperclass as ParameterizedType
        val clazz1 = type.actualTypeArguments[0] as Class<VM>
        mViewModel = ViewModelProvider(this)[clazz1]

        val clazz2 = if (type.actualTypeArguments.size <= 1) {
            FragmentBaseRvBinding::class.java
        } else {
            type.actualTypeArguments[1] as Class<SV>
        }
        val method = clazz2.getMethod("inflate", LayoutInflater::class.java)
        mViewBinding = method.invoke(null, layoutInflater) as SV
    }


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mBaseViewBinding = FragmentBaseBinding.inflate(layoutInflater)

        registerEvent()

        var layoutParams = RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT
        )
        mViewBinding.root.layoutParams = layoutParams
        mBaseViewBinding.rlContent.addView(mViewBinding.root)
        return mBaseViewBinding.root
    }

    private fun initViewModel() {
        mViewModel.mIsShowStatus.observe(this) {
            it?.run {
                when (index) {
                    0 -> {
                        showLoading(tip)
                    }
                    1 -> {
                        showContent()
                    }
                    2 -> {
                        showError()
                    }
                    3 -> {
                        hideLoading()
                    }
                    4 -> {
                        toLogin()
                    }
                }
            }
        }
        initObserve()
    }

    open fun initObserve() {

    }

    abstract fun init()

    open fun initListener() {

    }

    open fun initRequest() {

    }

    override fun onResume() {
        super.onResume()
        if (mIsVisible) {
            initViewModel()
            init()
            initListener()
            initRequest()
            mIsVisible = false
        }
    }


    private fun toLogin() {
        (requireActivity() as BaseActivity<*, *>).toLogin()
    }

    /**
     * 显示加载中
     */
    open fun showLoading(tip: String) {
        activity?.run {
            if (this is BaseActivity<*, *>) {
                this.showLoading(tip)
            }
        }
        mBaseViewBinding.rlContent.isClick = true
    }


    /**
     * 隐藏加载中
     */
    open fun hideLoading() {
        if (requireActivity() is BaseActivity<*, *>) {
            (requireActivity() as BaseActivity<*, *>).hideLoading()
        }
        mBaseViewBinding.rlContent.isClick = false
    }


    /**
     * 显示错误页面
     */
    open fun showError() {
        hideLoading()

        if (mErrorView == null) {
            mErrorView = mBaseViewBinding.root.findViewById<ViewStub>(R.id.vs_error_refresh).inflate()
            mLoadingErrorBinding = LayoutLoadingErrorBinding.bind(mErrorView!!)
            mLoadingErrorBinding.clError.clicks {
                onToRequest()
            }
        } else {
            mErrorView?.visibility
        }

        if (mViewBinding.root.isVisible) {
            mViewBinding.root.gone()
        }

    }

    /**
     * 显示正常页面
     */
    open fun showContent() {
        if (mErrorView?.visibility != View.GONE) {
            mErrorView?.visibility = View.GONE
        }
        mErrorView?.let {
            if (it.isVisible) {
                it.gone()
            }
        }

        if (mViewBinding.root.isGone) {
            mViewBinding.root.visible()
        }
    }

    /**
     * 错误界面的点击事件
     */
    open fun onToRequest() {
        initRequest()
    }

    override fun onDestroy() {
        super.onDestroy()
        unregisterEvent()
    }

    /**
     * 消息、事件接收回调
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    open fun handleEvent(msg: EventMessage) {

    }


    /**
     * 设置Adapter
     */
    open fun setRvAdapter(
        recycle: RecyclerView,
        manager: RecyclerView.LayoutManager,
        adapter: RecyclerView.Adapter<*>
    ) {
        recycle.layoutManager = manager
        recycle.adapter = adapter
    }

    open fun emptyView(): LayoutLoadingEmptyBinding {
        return LayoutLoadingEmptyBinding.inflate(layoutInflater, null, false)
    }


    open fun getTitleChar(): String = ""
    open fun getItemId(): Long = 1L

    fun showToast(message: String) {
        ToastUtils.getDefaultMaker()
            .setBgResource(R.drawable.trtcliveroom_message_background)
            .setTextColor(Color.WHITE)
            .setGravity(Gravity.CENTER, 0, 0)
            .setMode(ToastUtils.MODE.DARK)
            .setDurationIsLong(false)
            .show(message)
    }

    fun showToast(message: Int) {
        ToastUtils.getDefaultMaker()
            .setBgResource(R.drawable.trtcliveroom_message_background)
            .setTextColor(Color.WHITE)
            .setGravity(Gravity.CENTER, 0, 0)
            .setMode(ToastUtils.MODE.DARK)
            .setDurationIsLong(false)
            .show(getString(message))
    }

    fun showLongToast(message: String) {
        ToastUtils.getDefaultMaker()
            .setBgResource(R.drawable.trtcliveroom_message_background)
            .setTextColor(Color.WHITE)
            .setGravity(Gravity.CENTER, 0, 0)
            .setMode(ToastUtils.MODE.DARK)
            .setDurationIsLong(true)
            .show(message)
    }

    fun showLongToast(message: Int) {
        ToastUtils.getDefaultMaker()
            .setBgResource(R.drawable.trtcliveroom_message_background)
            .setTextColor(Color.WHITE)
            .setGravity(Gravity.CENTER, 0, 0)
            .setMode(ToastUtils.MODE.DARK)
            .setDurationIsLong(true)
            .show(getString(message))
    }

    /**
     * 下载apk
     */
    fun downApk(versionName: String, updateContent: String, url: String) {
        DownloadManager.getInstance(requireActivity())
            .setApkVersionName(versionName)
            .setApkDescription(updateContent)
            .setShowNewerToast(true)
            .setApkName("${getString(R.string.app_name)}${versionName}.apk")
            .setApkUrl(url)
            .setSmallIcon(R.mipmap.ic_launcher)
            .download()
    }
}